Skip to content

Controls, environment, observation, and the first gallery screens - #22

Merged
colemancda merged 5 commits into
masterfrom
feature/controls
Jul 23, 2026
Merged

Controls, environment, observation, and the first gallery screens#22
colemancda merged 5 commits into
masterfrom
feature/controls

Conversation

@colemancda

Copy link
Copy Markdown
Member

Fifth step of the Compose-backed architecture (#18#21). With the pipeline proven end-to-end in #21, this grows the vocabulary: form controls, @Environment/@Observable, effect modifiers, and the first seven gallery screens — restored and rendering through Compose.

Core (host-tested)

  • Primitives: Text(verbatim:), ScrollView, Color (as a fill view), Image, ProgressView, Slider, TextField, Picker (with .tag), plus LazyVStack/LazyHStack aliases.
  • @Environment: object injection down a subtree via .environment(_:), read by @Environment(Model.self). Values flow down evaluation and never cross the bridge.
  • @Observable: evaluate() wraps the body walk in withObservationTracking; a later mutation of any observed property schedules re-evaluation exactly like a @State write, re-arming each pass. Both use the same reflection seam as @State.
  • Modifiers: cornerRadius, offset, rotationEffect, scaleEffect, opacity.

swift test: 18 tests, all passing — adds slider/text-field binding round-trips, picker tag extraction + selection mapping, environment injection reaching a nested @Environment, and an @Observable mutation firing the change hook.

Interpreter

New node types: ScrollView (scroll state), Color, ProgressView (linear/circular), Slider, TextField, Picker (dropdown). TextField uses uncontrolled-with-reconciliation — Compose owns the TextFieldValue, lastSent tracks the pushed value so an echo leaves the cursor alone and an external change adopts Swift's value with the cursor at the end. Modifier folds added for clip/offset/rotation/scale/opacity.

Gallery

Text, Buttons, Stacks, State, Controls, Modifiers, and Observation screens restored verbatim and driven through the Compose renderer, selected by a Picker (full NavigationStack/List navigation returns in the next step). The host content now insets from the system bars (safeDrawingPadding), fixing the R4 status-bar overlap.

Verification

On the emulator:

  • Controls: toggle flips and drives its bound label ("Toggle is off" → "on") — the full Compose-event → JNI → Swift @State → re-evaluate → recompose round trip. Indeterminate spinner, determinate bar, slider, text field all render.
  • Modifiers: all seven render correctly — padding, frame 200×60, background, clip+corner-radius, offset, rotation, scale. This is the exact modifier suite that took the entire old Phase 1 to get working against classic views; here it's plain data.
  • Picker navigation between all seven screens works.

Note

AndroidKit must not be imported by app code (its AndroidView.View collides with the core's View); the umbrella re-exports the core, and AndroidSwiftUILog covers logging. The gallery screens compile unchanged against real SwiftUI on Apple platforms via the #if canImport gate.

Text(verbatim:), ScrollView, Color/Image/ProgressView/Slider/TextField/Picker
primitives with their bindings; @Environment object injection and @observable
change tracking through the same reflection seam as @State; and the
cornerRadius/offset/rotation/scale/opacity modifiers.
ScrollView, Color, ProgressView, Slider, TextField (uncontrolled-with-
reconciliation so the cursor survives), Picker via a dropdown, and the
clip/offset/rotation/scale/opacity modifier folds.
Text, Buttons, Stacks, State, Controls, Modifiers, and Observation screens
render through the Compose pipeline; NavigationStack navigation returns later.
@colemancda
colemancda merged commit 4939464 into master Jul 23, 2026
6 checks passed
@colemancda
colemancda deleted the feature/controls branch July 23, 2026 01:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant